package ar.edu.utn.frba.dds.opendesigners.escalas;

import java.util.ArrayList;
import java.util.List;

import ar.edu.utn.frba.dds.opendesigners.ParametroBusqueda;
import ar.edu.utn.frba.dds.opendesigners.aerolineas.AerolineaAdapter;
import ar.edu.utn.frba.dds.opendesigners.resultados.ResultadoBusqueda;
import ar.edu.utn.frba.dds.opendesigners.resultados.Asiento;
import ar.edu.utn.frba.dds.opendesigners.resultados.VueloDirecto;

//Posibilita que arme una estructura tipo "arbol" con origen y una lista de destinos posibles.
public class Rama {
	private VueloDirecto vuelo;			//Datos del vuelo que llega a esta "rama" 
	private ArrayList<Rama> destinos;	//Lista de otras "ramas" con vuelos que salen de donde llega este
	
	public Rama(VueloDirecto _vuelo){
		this.vuelo = _vuelo;
		this.destinos = new ArrayList<Rama>();
	}
	
	private void agregarTramoDestino(VueloDirecto _vuelo){
		Rama nuevaRama = new Rama(_vuelo);
		this.destinos.add(nuevaRama);
	}

	public void agregarTramos(ParametroBusqueda param,	AerolineaAdapter aerolinea, int maxEscalas, Boolean reversa) {
		
		
		if (reversa){
			param.setDestino(this.vuelo.getOrigen()); //El origen de estos vuelos son el destino del vuelo que llego a esta rama
			param.setFecha(this.vuelo.getFechaSalida("dd/MM/yyyy")); //Mismo con la fecha de llegada
			
			//Si no tengo mas escalas, tengo que buscar vuelos que vayan al destino. Sino, no me importa cual.
			if (maxEscalas > 0){
				//Si todavia puedo buscar mas escalas, entonces no me importa el origen, busco todo
				param.setOrigen(null);
			}
		}
		else{
			param.setOrigen(this.vuelo.getDestino()); //El origen de estos vuelos son el destino del vuelo que llego a esta rama
			param.setFecha(this.vuelo.getFechaLlegada("dd/MM/yyyy")); //Mismo con la fecha de llegada
			
			//Si no tengo mas escalas, tengo que buscar vuelos que vayan al destino. Sino, no me importa cual.
			if (maxEscalas > 0){
				//Si todavia puedo buscar mas escalas, entonces no me importa el destino, busco todo
				param.setDestino(null);
			}
		}
		
		//Hago una busqueda
		ResultadoBusqueda resultadoParcialOrigen = aerolinea.buscar(param);
		this.cargarListaTramos(resultadoParcialOrigen, reversa);
		
		//Si todavia tengo "escalas libres", busco otra vez
		if (maxEscalas > 0){
			for (Rama rama : this.destinos){
				rama.agregarTramos(param, aerolinea,  maxEscalas - 1, reversa);
			}
		}
	}
	
	public void cargarListaTramos(ResultadoBusqueda lista, Boolean reversa){
		for (Asiento vuelo : lista.getListaResultados()){
			if (!reversa){
				if (vuelo.getFechaSalida().esPosterior(this.vuelo.getFechaLlegada())){
					this.agregarTramoDestino((VueloDirecto) vuelo);
				}
			}
			else{
				if (vuelo.getFechaLlegada().esAnterior(this.vuelo.getFechaSalida())){
					this.agregarTramoDestino((VueloDirecto) vuelo);
				}
			}
		}
	}
	
	public List<List<VueloDirecto>> desmenuzar(){
		List<List<VueloDirecto>> listaVuelos = new ArrayList<List<VueloDirecto>>(); //Esto se va a devolver
		
		//Si tengo "destinos", soy una rama intermedia 
		if (this.destinos.size() > 0){
			List<List<VueloDirecto>> vuelosRama; //Esto contiene lo que me devueve cada rama
			List<VueloDirecto> listaTemp;  //Con esta copia trabajo en cada resultado de la rama
			//Le pido a cada destino de las ramas...
			for (Rama ramita : this.destinos){
				//... que me devuelva su lista
				vuelosRama = ramita.desmenuzar();
				
				//Y a cada uno, le agrego "yo" y lo cargo a la lista
				for (List<VueloDirecto> vuelos : vuelosRama){
					listaTemp = vuelos;
					//Agrego al principio de cada uno de lo que me devuelven, a este vuelo
					listaTemp.add(0, this.vuelo);
					
					//Y finalmente, lo agrego a la lista de lo que se devuelve al final.
					listaVuelos.add(listaTemp); 
				}
			}
		}
		else{
			//Soy la ultima rama. A ver como me las ingenio para hacer esto transparentemente para los demas.
			//Tengo que cargar el listaVuelos con solo yo.
			List<VueloDirecto> listaResultado = new ArrayList<VueloDirecto>();
			listaResultado.add(this.vuelo);
			
			listaVuelos.add(listaResultado);
		}
		
		return listaVuelos;
	}
	
}
